﻿/*
 * This software is the confidential and proprietary
 * information of NetBay
 * Such confidential information should not be disclosed
 * NetBay copyright(c) 2010
 */

#region Using

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using NetBay.Core.BusinessEntities;
using NetBay.Core.Log;
using Rio.Doc.Business.Repository.Translator;
using NetBay.Core.BusinessEntities.Versioning;
using Rio.Doc.DataAccess;
using Rio.Manager.Business.Repository;

#endregion

namespace Rio.Doc.Business.Repository
{
    /// <summary>
    /// Document type Repository
    /// </summary>
    public class DocumentRepository : DocumentDer
    {

        /// <summary>
        /// Returns the number of user declared
        /// </summary>
        /// <returns>then number of rows in the table</returns>
        public static ReturnLong GetNbDocument()
        {
            var l_oReturnLong = new ReturnLong();
            IDataReader l_oIDataReader = DA_Document.GetNbDocument();
            using ( l_oIDataReader )
            {
                while ( l_oIDataReader.Read() )
                {
                    l_oReturnLong.Value = long.Parse(l_oIDataReader["NbDoc"].ToString());
                }
            }
            return l_oReturnLong;
        }

        /// <summary>
        /// Returns all document that match criterias from a folder 
        /// </summary>
        /// <param name="p_lUserId">User ID</param>
        /// <param name="p_lFolderTypeId">FolderType ID</param>
        /// <param name="p_lFolderId">Folder ID</param>
        /// <returns>The list of all document that match criterias from a folder</returns>
        public static List<Document> GetDocumentByFolder(long p_lUserId, long p_lFolderTypeId, long p_lFolderId)
        {            
            // Finaly traslate results into a list of documents
            var l_oDocuments = DocumentTranslator.TranslateDocuments(DA_Document.GetDocumentByFolder(p_lUserId, p_lFolderTypeId, p_lFolderId));

            //Only if the td have a versionning model
            bool hasVersionning = DA_FolderType.FolderTypeHasVersionning(p_lFolderTypeId);
            if (hasVersionning)
            {
                if (l_oDocuments != null && l_oDocuments.Count > 0)
                {
                    AddVersionInformations(ref l_oDocuments);
                }
            }
            return l_oDocuments;
            
        }

        /// <summary>
        /// Returns all deleted document that match criterias from a folder 
        /// </summary>
        /// <param name="p_lUserId">User ID</param>
        /// <param name="p_lFolderTypeId">FolderType ID</param>
        /// <param name="p_lFolderId">Folder ID</param>
        /// <returns>The list of all document that match criterias from a folder</returns>
        public static List<Document> GetDeletedDocumentByFolder(long p_lUserId, long p_lFolderTypeId, long p_lFolderId)
        {
            // Finaly traslate results into a list of documents
            var l_oDocuments = DocumentTranslator.TranslateDocuments(DA_Document.GetDeletedDocumentByFolder(p_lUserId, p_lFolderTypeId, p_lFolderId));
            foreach (var lODocument in l_oDocuments)
            {
                lODocument.Deleted = true;
            }
            return l_oDocuments;
        }
        
        /// <summary>
        /// Retrive al messages sent by a user
        /// </summary>
        /// <param name="p_lMessageFlowId">The message flow identifier</param>
        /// <returns>All documents from a message flow</returns>
        public static List<Document> GetDocumentByMessageFlow(long p_lMessageFlowId)
        {
            // Finaly traslate results into a list of documents
            var l_oDocuments = DocumentTranslator.TranslateDocuments(DataAccess.DA_Document.GetDocumentByMessageFlow(p_lMessageFlowId));
            if (l_oDocuments != null && l_oDocuments.Count > 0)
            {
                AddVersionInformations(ref l_oDocuments);
            }
            return l_oDocuments;
        }

        /// <summary>
        /// Retreive historical message flow by a group
        /// </summary>
        /// <param name="p_lGroupId">Group ID</param>
        /// <param name="p_lDocumentId">Document ID</param>
        /// <param name="p_lMsgFlowId">MessageFlow ID</param>
        /// <returns>DataReader with historical</returns>
        public static List<Document> GetDocumentByGroupMessageFlow(long p_lGroupId, long p_lMsgFlowId, int p_iFilteredByState)
        {
            var l_oReturnLong = new List<Document>();

            try
            {
                // Finaly traslate results into a list of documents
                l_oReturnLong = DocumentTranslator.TranslateDocuments(DataAccess.DA_Document.GetDocumentByGroupMessageFlow(p_lGroupId, p_lMsgFlowId, p_iFilteredByState));
            }
            catch (Exception ex)
            {
                var l_oStateMessageFlow = new Document("(p_lGroupId<" + p_lGroupId + "> p_lMsgFlowId<" + p_lMsgFlowId + "> p_iFilteredByState<" + p_iFilteredByState + ">)", ex);
                LogManager.Instance().LogError(l_oStateMessageFlow.FullErrorMessage);
                l_oReturnLong.Add(l_oStateMessageFlow);
            }

            return l_oReturnLong;

        }
        
        /// <summary>
        /// Update documents rank
        /// </summary>
        /// <param name="p_szDocumentNewRank">The documents and thier new ranks. RD_NO;RANK;#RD_NO;RANK;#RD_NO;RANK;#RD_NO;RANK;#</param>
        /// <returns>a ReturnBoolean object</returns>
        public static ReturnBoolean UpdateDocumentRank(string p_szDocumentNewRank)
        {
            var l_oRet = new ReturnBoolean();
            try
            {
                l_oRet.Value = DataAccess.DA_Document.UpdateDocumentRank(p_szDocumentNewRank);
            }
            catch (Exception ex)
            {
                l_oRet = new ReturnBoolean("(p_szDocumentNewRank<" + p_szDocumentNewRank + ">)", ex);
                LogManager.Instance().LogError(l_oRet.FullErrorMessage);
            }
            return l_oRet;
        }

        /// <summary>
        /// Update documents item
        /// </summary>
        /// <param name="p_lDocumentId">Document ID</param>
        /// <param name="p_szItem">Document Item</param>
        /// <returns>ReturnBoolean object</returns>
        public static ReturnBoolean UpdateDocumentItem(long p_lDocumentId, string p_szItem)
        {
            var l_oRet = new ReturnBoolean();
            try
            {
                l_oRet.Value = DataAccess.DA_Document.UpdateDocumentItem(p_lDocumentId, p_szItem);
            }
            catch (Exception ex)
            {
                l_oRet = new ReturnBoolean("(p_lDocumentId<" + p_lDocumentId + "> p_szItem<" + p_szItem + ">)", ex);
                LogManager.Instance().LogError(l_oRet.FullErrorMessage);
            }
            return l_oRet;
        }

        /// <summary>
        /// Returns all document that match criterias from a folder
        /// </summary>
        /// <param name="p_lUserId"></param>
        /// <param name="p_szRdImage">Rd Image</param>
        /// <param name="p_oFolderTypeRepository"></param>
        /// <returns>The list of all document that match criterias from a folder</returns>
        public static Document GetDocumentByRdImage(long p_lUserId, string p_szRdImage, FolderTypeRepository p_oFolderTypeRepository)
        {
            List<Document> l_oDocuments = null;
            Document l_oReturnDoc = null;
            // Get documents by folder
            var l_oDR = DA_Document.GetDocumentByRdImage(p_lUserId, p_szRdImage, p_oFolderTypeRepository.Identifier);
            
            if (l_oDR != null )
            {
                // Finaly traslate results into a list of documents
                l_oDocuments = DocumentTranslator.TranslateDocuments(l_oDR);
                if (l_oDocuments != null && l_oDocuments.Count > 0)
                {
                    foreach (var l_oDocument in l_oDocuments)
                    {
                        var l_oFolderDR = DA_Folder.GetFolderByDocumentId(l_oDocument.FolderIdentifier, p_lUserId);

                        var l_oFolders = FolderTranslator.TranslateFolder(l_oFolderDR, p_oFolderTypeRepository.LstIndex,
                                                                            p_oFolderTypeRepository.Name);
                        if (l_oFolders != null && l_oFolders.Count == 1)
                        {
                            l_oDocument.Folder = l_oFolders[0];
                        }
                    }
                    l_oReturnDoc = l_oDocuments.First();

                    //add versioning features
                    AddVersionInformations(ref l_oReturnDoc);
                }
            }
            
            return l_oReturnDoc;
        }

        /// <summary>
        /// Returns all document that match criterias from a folder
        /// </summary>
        /// <param name="p_lUserId">User ID</param>
        /// <param name="p_oFolderTypeRepository"></param>
        /// <param name="p_szNote">regular expression applied into document's note</param>
        /// <param name="p_szCreditPhoto">regular expression applied into creditPhoto's note</param>
        /// <param name="p_szAuteur"></param>
        /// <param name="p_szFichierOrigine"></param>
        /// <param name="p_bLazyLoading"></param>
        /// <returns>The list of all document that match criterias from a folder</returns>
        public static List<Document> SearchDocuments(long p_lUserId, FolderTypeRepository p_oFolderTypeRepository, string p_szNote = null,
                                    string p_szCreditPhoto = null, string p_szAuteur = null, string p_szFichierOrigine = null, bool p_bLazyLoading = false)
        {
            var l_oDocuments = new List<Document>();

            // Fonctional Rule 6.1.5-2
            if (string.IsNullOrWhiteSpace(p_szNote) == false || string.IsNullOrWhiteSpace(p_szCreditPhoto) == false || string.IsNullOrWhiteSpace(p_szAuteur) == false || string.IsNullOrWhiteSpace(p_szFichierOrigine) == false)
            {
                // Get documents by folder
                var l_oDR = DA_Document.SearchDocuments(p_lUserId, p_oFolderTypeRepository.Identifier, p_szNote, p_szCreditPhoto, p_szAuteur, p_szFichierOrigine);
                using (l_oDR)
                {
                    // Finaly traslate results into a list of documents
                    l_oDocuments = DocumentTranslator.TranslateDocuments(l_oDR);
                }

                Dictionary<String, Folder> l_FolderList = new Dictionary<String, Folder>();  

                if (p_bLazyLoading)
                {
                    foreach (var l_oDocument in l_oDocuments)
                    {
                        if (!l_FolderList.ContainsKey(l_oDocument.FolderIdentifier))
                        {
                            var l_oFolders = FolderTranslator.TranslateFolder(DA_Folder.GetFolderByDocumentId(l_oDocument.FolderIdentifier, p_lUserId), p_oFolderTypeRepository.LstIndex, p_oFolderTypeRepository.Name);
                            if (l_oFolders != null && l_oFolders.Count == 1)
                            {
                                l_oDocument.Folder = l_oFolders[0];
                                l_FolderList.Add(l_oDocument.FolderIdentifier, l_oFolders[0]);
                            }
                        }
                        else
                        {
                            l_oDocument.Folder = l_FolderList[l_oDocument.FolderIdentifier];
                        }
                    }
                }
            }

            return l_oDocuments;
        }

        /// <summary>
        /// Delete a document
        /// </summary>
        /// <param name="p_lDocumentId">Document ID</param>
        public static void DeleteDocument(long p_lDocumentId)
        {
            DA_Document.DeleteDocument(p_lDocumentId);
        }
        
        /// <summary>
        /// Restore a document
        /// </summary>
        /// <param name="p_lDocumentId">Document ID</param>
        public static void RestoreDocument(long p_lDocumentId)
        {
            DA_Document.RestoreDocument(p_lDocumentId);
        }

        /// <summary>
        /// Remove a document
        /// </summary>
        /// <param name="p_lDocumentId">Document ID</param>
        public static void RemoveDocument(long p_lDocumentId)
        {
            DA_Document.RemoveDocument(p_lDocumentId);
        }

        /// <summary>
        /// Update document's infos
        /// </summary>
        /// <param name="p_lDocumentId">Document ID</param>
        /// <param name="p_szNote">Note</param>
        /// <param name="p_szAuthor">Author</param>
        /// <param name="p_szPhotoCredit">Photo credit</param>
        /// <returns>Status of execution</returns>
        public static List<ReturnObject> UpdateDocument(long p_lDocumentId, string p_szNote, string p_szAuthor, string p_szPhotoCredit)
        {
            var l_lstReturnObject = new List<ReturnObject>();
            DA_Document.UpdateDocument(p_lDocumentId, p_szNote, p_szAuthor, p_szPhotoCredit);
            return l_lstReturnObject;
        }

        /// <summary>
        /// Set FullTextIndex to 2 for indexed files
        /// </summary>
        /// <param name="p_sDocumentList"></param>
        public static void UpdateDocumentsForFullText(string p_sDocumentList)
        {
            DA_Document.UpdateDocumentsForFullText(p_sDocumentList);
        }

        /// <summary>
        /// Add a document in our EDM
        /// </summary>
        /// <param name="p_lFolderTypeId">FolderType ID</param>
        /// <param name="p_lFolderId">Folder ID</param>
        /// <param name="p_szIdDoc">Id Doc</param>
        /// <param name="p_szSourceDocumentName">Original document name</param>
        /// <param name="p_szDocumentName">Document name into our EDM</param>
        /// <param name="p_szFolderPath">Path to reach our document in our EDM</param>
        /// <param name="p_szItem">Code for Item where the document is associated</param>
        /// <param name="p_szNote">Note associated at document</param>
        /// <param name="p_szAuthor">Author of document</param>
        /// <param name="p_szPhotoCredit">Credit for the photo</param>
        /// <param name="p_szVideoLenght">Video Lenght</param>
        /// <param name="p_bFullTextRequested">Indicate if a fulltext is requested for this document</param>
        /// <returns>DocumentID</returns>
        public static long AddDocument(long p_lFolderTypeId, long p_lFolderId, string p_szIdDoc,
            string p_szSourceDocumentName, string p_szDocumentName, string p_szFolderPath, string p_szItem,
            string p_szNote, string p_szAuthor, string p_szPhotoCredit, string p_szVideoLenght, bool p_bFullTextRequested
            )
        {
            // Get documents by folder
             return DA_Document.AddDocument(p_lFolderTypeId, p_lFolderId, p_szIdDoc,
                p_szSourceDocumentName, p_szDocumentName, p_szFolderPath, p_szItem,
                p_szNote, p_szAuthor, p_szPhotoCredit, p_szVideoLenght, p_bFullTextRequested);
        }

        /// <summary>
        /// Add a list of document
        /// </summary>
        /// <param name="p_oDocumentList">The p_o document list.</param>
        /// <param name="p_bInsertMode">if set to <c>true</c> [P_B insert mode].</param>
        /// <returns></returns>
        public static List<Document> AddDocument(List<Document> p_oDocumentList, bool p_bInsertMode)
        {
            return DA_Document.AddDocument(p_oDocumentList, p_bInsertMode);
        }

        /// <summary>
        /// Retreive the documents by Document ID
        /// </summary>
        /// <param name="p_lDocumentId">Document Id</param>
        /// <returns>
        /// The document
        /// </returns>
        public static Document GetDocumentById(long p_lDocumentId)
        {
            // Finaly traslate results into a list of documents
            var l_oDocuments = DocumentTranslator.TranslateDocuments(DataAccess.DA_Document.GetDocumentById(p_lDocumentId));
            AddVersionInformations(ref l_oDocuments);
            return l_oDocuments.First();
        }

        /// <summary>
        /// Development of document's item
        /// </summary>
        public override void SetItemList()
        {
            throw new NotImplementedException();
        }

           
        #region Versioning

        /// <summary>
        /// Add a version to the specified document identifier
        /// </summary>
        /// <param name="p_lDocId">Document identifier</param>
        /// <param name="p_lUserId">User Identifier</param>
        /// <param name="p_sFileName">New FileName</param>
        /// <param name="p_lModelId">The P_L model id.</param>
        /// <param name="IsMajor">Indicate whether the new version is major</param>
        /// <returns>
        /// Return new version identifier
        /// </returns>
        public static long AddVersion(long p_lDocId, long p_lUserId, string p_sFileName, long p_lModelId, bool IsMajor)
        {
            return DocumentTranslator.TranslateAddVersion(DataAccess.DA_Document.AddVersion(p_lDocId, p_lUserId, p_sFileName,p_lModelId, IsMajor));
        }

        /// <summary>
        /// Add a major version to the specified document identifier
        /// </summary>
        /// <param name="p_lDocId">Document identifier</param>
        /// <param name="p_lUserId">User Identifier</param>
        /// <param name="p_lOldVersionId">The P_L old version id.</param>
        /// <param name="p_lModelId">The P_L model id.</param>
        /// <param name="IsMajor">if set to <c>true</c> [is major].</param>
        /// <returns>
        /// Return new version identifier
        /// </returns>
        public static long AddVersionFromOld(long p_lDocId, long p_lUserId, long p_lOldVersionId, long p_lModelId, bool IsMajor)
        {
            return DocumentTranslator.TranslateAddVersion(DataAccess.DA_Document.AddVersionFromOld(p_lDocId, p_lUserId, p_lOldVersionId, p_lModelId, IsMajor));
        }

        /// <summary>
        /// Change State version by version identifier
        /// </summary>
        /// <param name="VersionId">The version id.</param>
        /// <param name="NewState">New state version</param>
        /// <returns>
        /// True if ok
        /// </returns>
        public static Boolean ChangeVersioningStateById(long VersionId, VersionState NewState)
        {
            return Rio.Doc.DataAccess.DA_Document.ChangeVersioningStateById(VersionId, NewState);
        }

        /// <summary>
        /// CheckOut the version
        /// </summary>
        /// <param name="VersionId">Version identifier</param>
        /// <returns>True if ok</returns>
        public static Boolean CheckOutVersion(long VersionId)
        {
            return Rio.Doc.DataAccess.DA_Document.ChangeVersioningStateById(VersionId, VersionState.Checkout);
        }

        /// <summary>
        /// CheckIn the version
        /// </summary>
        /// <param name="VersionId">Version identifier</param>
        /// <returns>True if ok</returns>
        public static Boolean CheckInVersion(long VersionId)
        {
            return Rio.Doc.DataAccess.DA_Document.ChangeVersioningStateById(VersionId, VersionState.Checkin);
        }

        /// <summary>
        /// Add version and overwrite it
        /// </summary>
        /// <param name="p_lDocId">Document identifier</param>
        /// <param name="p_lUserId">User identifier</param>
        /// <param name="p_sFileName">New filename</param>
        /// <returns></returns>
        public static long OverwriteVersion(long p_lDocId, long p_lUserId, string p_sFileName)
        {
            return DocumentTranslator.TranslateAddVersion(DataAccess.DA_Document.OverwriteVersion(p_lDocId, p_lUserId, p_sFileName));
        }

        /// <summary>
        /// Get a version by identifier
        /// </summary>
        /// <param name="VersionId">Version identifier</param>
        /// <returns>The versioning item</returns>
        public static VersioningItem GetVersion(long VersionId)
        {
            return DocumentTranslator.GetVersion(Rio.Doc.DataAccess.DA_Document.GetVersion(VersionId));
        }

        /// <summary>
        /// Returns the current version identifier.
        /// </summary>
        /// <param name="DocId">Document identifier</param>
        /// <returns>Version identifier</returns>
        public static long GetCurrentVersion(long DocId)
        {
            return DocumentTranslator.GetCurrentVersion(Rio.Doc.DataAccess.DA_Document.GetCurrentVersion(DocId));
        }

        /// <summary>
        /// Returns the current version identifier.
        /// </summary>
        /// <param name="DocId">Document identifier</param>
        /// <returns>Version identifier</returns>
        public static VersioningItem GetLastVersion(long DocId)
        {
            return DocumentTranslator.GetVersion(Rio.Doc.DataAccess.DA_Document.GetLastVersion(DocId));
        }

        /// <summary>
        /// Remove checkout on the version
        /// </summary>
        /// <param name="VersionId">Version identifier</param>
        /// <returns>True if removed correctly.</returns>
        public static Boolean UndoCheckout(long VersionId)
        {
            return Rio.Doc.DataAccess.DA_Document.UndoCheckout(VersionId);
        }

        /// <summary>
        /// Add versioning informations to all documents
        /// </summary>
        /// <param name="l_oDocuments">A list of documents</param>
        public static void AddVersionInformations(ref List<Document> l_oDocuments)
        {
            // Each document have the same Document Model
            var l_oModelVersion = VersioningRepository.GetVersionModel(l_oDocuments[0].FolderTypeIdentifier);

            foreach (var l_oDocument in l_oDocuments)
            {
                // Add the model definition
                if (l_oModelVersion != null && l_oModelVersion.ModelType != VersionType.None)
                {
                    l_oDocument.CurrentModelVersion = l_oModelVersion;
                    l_oDocument.IsVersionable = true;
                }
                else
                {
                    l_oDocument.IsVersionable = false;
                }

                // Add all versions
                l_oDocument.AllVersion = DocumentTranslator.TranslateDocumentsWithAllVersion(Rio.Doc.DataAccess.DA_Document.GetAllVersionDocumentById(l_oDocument.Identifier));
            }
        }

        /// <summary>
        /// Add versioning informations to the document
        /// </summary>
        /// <param name="l_oDocument"></param>
        private static void AddVersionInformations(ref Document l_oDocument)
        {
            // Each document have the same Document Model
            var l_oModelVersion = VersioningRepository.GetVersionModel(l_oDocument.FolderTypeIdentifier); 

            // Add the model definition
            if (l_oModelVersion != null)
            {
                l_oDocument.CurrentModelVersion = l_oModelVersion;
                l_oDocument.IsVersionable = true;
            }
            else
            {
                l_oDocument.IsVersionable = false;
            }

            // Add all versions
            l_oDocument.AllVersion = DocumentTranslator.TranslateDocumentsWithAllVersion(Rio.Doc.DataAccess.DA_Document.GetAllVersionDocumentById(l_oDocument.Identifier));
        }

        #endregion

        #region Paste

        /// <summary>
        /// Paste the list of document to the destination folder. The isCut determine the source action  
        /// </summary>
        /// <param name="p_lDocId">List of document identifiers</param>
        /// <param name="DestinationFolderIdentifier">Destination folder identifier</param>
        /// <param name="isCut">True if is cut action, else copy</param>
        /// <param name="p_szItemRank">New item rank</param>
        /// <param name="isOldVersion">Indicate whether if the document is an old version. In this case there only one document in the list</param>
        /// <returns></returns>
        public static ReturnBoolean PasteDocument(long p_lDocId, string p_sDestinationFolderIdentifier, long FolderIdentifier, long p_sDestinationFolderTypeId, 
                                                  bool p_bisCut, string p_sItemRank = null, bool p_bisOriginalVersion = false, long VersionId = 0)
        {
            var l_oRet = new ReturnBoolean();
            try
            {
                l_oRet.Value = DataAccess.DA_Document.PasteDocument(p_lDocId, p_sDestinationFolderIdentifier, FolderIdentifier, p_sDestinationFolderTypeId, p_bisCut, p_sItemRank, p_bisOriginalVersion, VersionId);
            }
            catch (Exception ex)
            {
                l_oRet = new ReturnBoolean("(p_lDocumentId<" + p_lDocId + "> p_sDestinationFolderIdentifier<" + p_sDestinationFolderIdentifier + "> p_bisCut<" + p_bisCut + "> p_sItemRank<" + p_sItemRank + "> p_bisOldVersion<" + p_bisOriginalVersion.ToString() + ">", ex);
                LogManager.Instance().LogError(l_oRet.FullErrorMessage);
            }
            return l_oRet;
        }

        #endregion
    }
}
